package Controller;

import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.World;
import org.jbox2d.dynamics.joints.Joint;
import org.jbox2d.dynamics.joints.JointType;
import org.jbox2d.dynamics.joints.MouseJoint;
import org.mt4j.MTApplication;
import org.mt4j.components.MTComponent;
import org.mt4j.components.visibleComponents.shapes.MTRectangle;
import org.mt4j.input.inputData.InputCursor;
import org.mt4j.input.inputProcessors.IGestureEventListener;
import org.mt4j.input.inputProcessors.MTGestureEvent;
import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragEvent;
import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.MultipleDragProcessor;
import org.mt4j.util.MTColor;
import org.mt4j.util.math.Vector3D;

import processing.core.PApplet;

import GameObjects.PlayerBrick;

public class Player extends MTRectangle {
	
	private InputCursor one = null, two = null;
	private long score;
	private MTComponent physicsContainer;
	private MTColor playerColor;
	private PlayerBrick brick;
	private MTApplication app;
	private World world;
	private float scale;
	private float angle;
	private float x, y;
	private float distance;
	
	
	/**
	 * Defaultconstructor
	 */
	public Player(float _width, float _height, MTColor _playerColor, MTApplication _app,MTComponent _physicsContainer, World _world, float _scale){
		super(_width,_height, _app);
		
		this.setStrokeColor(_playerColor);
		this.setNoFill(true);
		this.unregisterAllInputProcessors();
		
		playerColor = _playerColor;
		app = _app;
		physicsContainer = _physicsContainer;
		world = _world;
		scale = _scale;		
		score = 0;
		
		MultipleDragProcessor tap = new MultipleDragProcessor(getRenderer());
		this.registerInputProcessor(tap);
		this.addGestureListener(MultipleDragProcessor.class, new IGestureEventListener() {
			public boolean processGestureEvent(MTGestureEvent ge) {
				DragEvent de = (DragEvent)ge;	
				MouseJoint mouseJoint;
				
				if(de.getId() == de.GESTURE_DETECTED){
					if(one == null){
						one = de.getDragCursor();
						
					}else if (two == null){
						two = de.getDragCursor();
					}
					if(one != null && two != null && brick == null){
						
						angle = PApplet.atan2(two.getCurrentEvtPosY()-one.getCurrentEvtPosY(), two.getCurrentEvtPosX()-one.getCurrentEvtPosX());
						distance = one.getPosition().distance(two.getPosition())/2;
						x = distance * PApplet.cos(angle); // + y * PApplet.sin(angle);  y = 0 here => not needed
						y = distance * PApplet.sin(angle); // - y * PApplet.cos(angle);  y = 0 here => not needed
						
						brick = new PlayerBrick(new Vector3D(one.getCurrentEvtPosX()+x, one.getCurrentEvtPosY()+y), 120, 20, playerColor, app, world, scale);
						brick.setPlayerAffinity((Player)de.getTargetComponent());
						brick.getBody().m_sweep.a = angle;
						brick.getBody().m_sweep.a0 = angle;
						physicsContainer.addChild(brick);
						
//						 integrated Physikhelpercode
						brick.getBody().wakeUp();
						mouseJoint = util.PhysicsHelper.createDragJoint(world, brick.getBody(),(one.getPosition().x + x)/scale, (one.getPosition().y + y)/scale );
						brick.setUserData("mouseJoint" + one.getId(), mouseJoint);
					}
					
				}else if(de.getId() == de.GESTURE_UPDATED){
					if(one != null && two != null){
						if(one.equals(de.getDragCursor()) || two.equals(de.getDragCursor())){
							
							angle = PApplet.atan2(two.getCurrentEvtPosY()-one.getCurrentEvtPosY(), two.getCurrentEvtPosX()-one.getCurrentEvtPosX());
							distance = one.getPosition().distance(two.getPosition())/2;
							x = distance * PApplet.cos(angle) + 0 * PApplet.sin(angle);
							y = distance * PApplet.sin(angle) - 0 * PApplet.cos(angle);
							
							// integrated Physikhelper code
							mouseJoint = (MouseJoint) brick.getUserData("mouseJoint" + one.getId());
							if (mouseJoint != null){
								mouseJoint.setTarget(new Vec2((one.getPosition().x + x)/scale, (one.getPosition().y + y)/scale ));
							}		
							
							brick.getBody().m_sweep.a = angle;
							brick.getBody().m_sweep.a0 = angle;
							
							
						}
					}					
				}else if(de.getId() == de.GESTURE_ENDED){
							
					if(one != null && one.equals(de.getDragCursor())){
						if(brick != null){
							destroyMJ();
							brick.destroy();
							brick = null;
						}
						one = null;
					}else if (two != null && two.equals(de.getDragCursor())){
						if(brick != null){
							destroyMJ();
							brick.destroy();
							brick = null;
						}
						two = null;
					}					
				}			
				
				return true;
			}
		});
		
		
	}
	
	private void destroyMJ(){
		
		MouseJoint mouseJoint = (MouseJoint) brick.getUserData("mouseJoint" + one.getId());
		if (mouseJoint != null){
			brick.setUserData("mouseJoint" + one.getId(), null);
//			theWorld.destroyJoint(mouseJoint);	
			//Only destroy the joint if it isnt already (go through joint list and check)
			for (Joint joint = world.getJointList(); joint != null; joint = joint.getNext()) {
				JointType type = joint.getType();
				switch (type) {
				case MOUSE_JOINT:
					MouseJoint mj = (MouseJoint)joint;
					if (brick.getBody().equals(mj.getBody1()) || brick.getBody().equals(mj.getBody2())){
//						theWorld.destroyJoint(mj);
						if (mj.equals(mouseJoint)) {
							world.destroyJoint(mj);
						}
					}
					break;
				default:
					break;
				}
			}
		}
		mouseJoint = null;		
	}
	
	
	
	
	/**
	 * @param _score
	 */
	public void addScore(int _score){
		score += _score;
	}
	
	/**
	 * Settermethod for the score
	 * @param _score
	 */
	public void setScore(long _score){
		score = _score;
	}
	
	/**
	 * Gettermethod for the score
	 * @return
	 */
	public long getScore(){
		return score;
	}
	
	/**
	 * Gettermethod for the color of a player
	 * @return
	 */
	public MTColor getPlayerColor(){
		return playerColor;
	}
	
	

}
